package com.gitee.qdbp.jdbc.biz;

import java.util.HashMap;
import java.util.Map;
import com.gitee.qdbp.able.jdbc.condition.TableJoin;
import com.gitee.qdbp.jdbc.api.CrudDao;
import com.gitee.qdbp.jdbc.api.JoinQueryer;
import com.gitee.qdbp.jdbc.api.QdbcBase;
import com.gitee.qdbp.jdbc.api.SqlBufferJdbcOperations;
import com.gitee.qdbp.jdbc.api.SqlDao;
import com.gitee.qdbp.jdbc.plugins.DbPluginHelper;
import com.gitee.qdbp.jdbc.plugins.SqlDialect;
import com.gitee.qdbp.jdbc.sql.SqlBuffer;
import com.gitee.qdbp.jdbc.sql.SqlBuilder;
import com.gitee.qdbp.jdbc.sql.build.CommonSqlTools;
import com.gitee.qdbp.jdbc.sql.build.CrudSqlHelper;
import com.gitee.qdbp.jdbc.sql.build.QuerySqlHelper;
import com.gitee.qdbp.jdbc.sql.parse.SqlFragmentContainer;
import com.gitee.qdbp.jdbc.stream.CrudStream;
import com.gitee.qdbp.jdbc.stream.SqlStream;
import com.gitee.qdbp.jdbc.utils.ParseTools;

/**
 * 基础增删改查对象的构造器
 *
 * @author 赵卉华
 * @version 190601
 */
public abstract class QdbcBaseImpl implements QdbcBase {

    /** SqlBuffer数据库操作类 **/
    private final SqlBufferJdbcOperations sqlJdbc;
    /** 执行SQL语句的处理接口 **/
    private final SqlDao sqlDao;
    /** SQL工具类 **/
    private final CommonSqlTools sqlTools;
    /** Sql片段容器 **/
    private final SqlFragmentContainer sqlContainer;

    private final Map<Class<?>, CrudDao<?>> crudDaoCache = new HashMap<>();
    /** 批量执行时的大小限制常量(0为无限制) **/
    protected static int DEFAULT_BATCH_SIZE = 500;
    /** 批量执行时的默认大小限制(0为无限制) **/
    protected int defaultBatchSize = DEFAULT_BATCH_SIZE;

    public QdbcBaseImpl(SqlBufferJdbcOperations sqlJdbc) {
        this.sqlJdbc = sqlJdbc;
        this.sqlContainer = new SqlFragmentContainer(this);
        this.sqlDao = new SqlDaoImpl(sqlContainer, sqlJdbc);
        this.sqlTools = new CommonSqlTools(this);
    }

    public void init() {
        if (sqlJdbc.plugins().getSqlFragmentOptions().isSqlTemplateScanOnStartup()) {
            this.sqlContainer.initSqlFiles();
        }
    }

    /** 批量执行时的默认大小限制(0为无限制) **/
    public int getDefaultBatchSize() {
        return defaultBatchSize;
    }

    /** 批量执行时的默认大小限制(0为无限制) **/
    public void setDefaultBatchSize(int batchSize) {
        this.defaultBatchSize = batchSize;
        for (CrudDao<?> item : crudDaoCache.values()) {
            if (item instanceof CrudDaoImpl) {
                ((CrudDaoImpl<?>) item).setDefaultBatchSize(defaultBatchSize);
            }
        }
    }

    /** {@inheritDoc} **/
    @Override
    public <T> CrudStream<T> crudStream(Class<T> clazz) {
        return new CrudStream<>(crudDao(clazz));
    }

    /** {@inheritDoc} **/
    @Override
    public SqlStream sqlStream() {
        return new SqlStream(sqlDao());
    }

    /** {@inheritDoc} **/
    @Override
    @SuppressWarnings("unchecked")
    public <T> CrudDao<T> crudDao(Class<T> clazz) {
        if (crudDaoCache.containsKey(clazz)) {
            return (CrudDao<T>) crudDaoCache.get(clazz);
        } else {
            CrudDaoImpl<T> instance = new CrudDaoImpl<>(clazz, this, sqlDao, sqlJdbc);
            instance.setDefaultBatchSize(this.defaultBatchSize);
            crudDaoCache.put(clazz, instance);
            return instance;
        }
    }

    /** {@inheritDoc} **/
    @Override
    public <T> JoinQueryer<T> joinQueryer(TableJoin tables, Class<T> resultType) {
        return new JoinQueryerImpl<>(tables, resultType, this, sqlJdbc);
    }

    @Override
    public ParseTools parseTools() {
        return sqlJdbc.plugins().parseTools();
    }

    @Override
    public CommonSqlTools sqlTools() {
        return sqlTools;
    }

    /** {@inheritDoc} **/
    @Override
    public CrudSqlHelper sqlHelper(Class<?> clazz) {
        return new CrudSqlHelper(clazz, this);
    }

    /** {@inheritDoc} **/
    @Override
    public QuerySqlHelper sqlHelper(TableJoin tables) {
        return new QuerySqlHelper(tables, this);
    }

    /** {@inheritDoc} **/
    @Override
    public SqlDao sqlDao() {
        return sqlDao;
    }

    /** {@inheritDoc} **/
    @Override
    public SqlDialect sqlDialect() {
        return sqlJdbc.sqlDialect();
    }

    @Override
    public SqlFragmentContainer sqlContainer() {
        return this.sqlContainer;
    }

    @Override
    public DbPluginHelper plugins() {
        return sqlJdbc.plugins();
    }

    @Override
    public SqlBuffer newSqlBuffer() {
        return new SqlBuffer(sqlDialect(), plugins());
    }

    @Override
    public SqlBuilder newSqlBuilder() {
        return new SqlBuilder(sqlDialect(), plugins());
    }

    /** {@inheritDoc} **/
    @Override
    public SqlBufferJdbcOperations sqlJdbc() {
        return this.sqlJdbc;
    }
}
